
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using ScrewTurn.Wiki.PluginFramework;
using System.Text;
using System.Globalization;

namespace ScrewTurn.Wiki {

	public partial class AllPages : BasePage {

        protected void Page_Load(object sender, EventArgs e) {
            Page.Title = Resources.Messages.AllPagesTitle + " - " + Settings.WikiTitle;

			if(Request["Cat"] != null) {
				if(Request["Cat"].Equals("-"))
					lblPages.Text = Resources.Messages.UncategorizedPages;
				else
					lblPages.Text = Resources.Messages.PagesOfCategory + " <i>" + Request["Cat"] + "</i>";
			}

			PrintPages();
			PrintTree();
        }

        public void PrintPages() {
			if(Request["View"] != null && Request["View"].ToLowerInvariant().Equals("tree")) {
				return;
			}

			StringBuilder sb = new StringBuilder();

			List<PageInfo> pages = new List<PageInfo>();
			// Categories Management
			if(Request["Cat"] != null) {
				if(Request["Cat"].Equals("-")) {
					pages.AddRange(Pages.Instance.GetUncategorizedPages());
				}
				else {
					CategoryInfo cat = Pages.Instance.FindCategory(Request["Cat"]);
					if(cat != null) {
						for(int i = 0; i < cat.Pages.Length; i++) {
							pages.Add(Pages.Instance.FindPage(cat.Pages[i]));
						}
					}
					else return;
				}
			}
			else {
				pages.AddRange(Pages.Instance.AllPages);
			}

			sb.Append(@"<div id=""ListDiv"">");

			if(Request["Cat"] == null) {
				sb.Append(@"<a href=""AllPages.aspx?View=Tree"">");
				sb.Append(Resources.Messages.ViewTree);
				sb.Append("</a><br /><br />");
			}
			else {
				sb.Append(@"<a href=""AllPages.aspx"">");
				sb.Append(Resources.Messages.AllPages);
				sb.Append(@"</a> - <a href=""Category.aspx"">");
				sb.Append(Resources.Messages.Categories);
				sb.Append("</a><br /><br />");
			}

			// Prepare ExtendedPageInfo array
			ExtendedPageInfo[] tempPageList = new ExtendedPageInfo[pages.Count];
			PageContent cnt;
			for(int i = 0; i < tempPageList.Length; i++) {
				cnt = Content.GetPageContent(pages[i], true);
				tempPageList[i] = new ExtendedPageInfo(pages[i], cnt.Title, cnt.LastModified, cnt.User);
			}

			// Prepare for sorting
			bool reverse = false;
			SortingMethod sortBy = SortingMethod.Title;
			if(Request["SortBy"] != null) {
				try {
					sortBy = (SortingMethod)Enum.Parse(typeof(SortingMethod), Request["SortBy"], true);
				}
				catch {
					// Backwards compatibility
					if(Request["SortBy"].ToLowerInvariant() == "date") sortBy = SortingMethod.DateTime;
				}
				if(Request["Reverse"] != null) reverse = true;
			}
			
			SortedDictionary<SortingGroup, List<ExtendedPageInfo>> sortedPages = PageSortingTools.Sort(tempPageList, sortBy, reverse);

			sb.Append(@"<table id=""PageListTable"" cellpadding=""2"" cellspacing=""0"">");
			sb.Append(@"<tr id=""PageListHeader"">");

			sb.Append(@"<td><p><b><a href=""AllPages.aspx?SortBy=Title"); // Title
			sb.Append((!reverse && sortBy == SortingMethod.Title ? "&amp;Reverse=1" : ""));
			sb.Append((Request["Cat"] != null ? "&amp;Cat=" + Tools.UrlEncode(Request["Cat"]) : ""));
			sb.Append(@""" title=""");
			sb.Append(Resources.Messages.SortByTitle);
			sb.Append(@""">");
			sb.Append(Resources.Messages.PageTitle);
			sb.Append((reverse && sortBy.Equals("title") ? " &uarr;" : ""));
			sb.Append((!reverse && sortBy.Equals("title") ? " &darr;" : ""));
			sb.Append("</a></b></p></td>");

			sb.Append(@"<td width=""12""><img src=""Images/Comment.png"" alt=""Comments"" /></td>"); // 

			sb.Append(@"<td><p><b><a href=""AllPages.aspx?SortBy=DateTime"); // Date
			sb.Append((!reverse && sortBy == SortingMethod.DateTime ? "&amp;Reverse=1" : ""));
			sb.Append((Request["Cat"] != null ? "&amp;Cat=" + Tools.UrlEncode(Request["Cat"]) : ""));
			sb.Append(@""" title=""");
			sb.Append(Resources.Messages.SortByDate);
			sb.Append(@""">");
			sb.Append(Resources.Messages.Modified);
			sb.Append((reverse && sortBy.Equals("date") ? " &uarr;" : ""));
			sb.Append((!reverse && sortBy.Equals("date") ? " &darr;" : ""));
			sb.Append("</a></b></p></td>");

			sb.Append(@"<td><p><b><a href=""AllPages.aspx?SortBy=User"); // User
			sb.Append((!reverse && sortBy == SortingMethod.User ? "&amp;Reverse=1" : ""));
			sb.Append((Request["Cat"] != null ? "&amp;Cat=" + Tools.UrlEncode(Request["Cat"]) : ""));
			sb.Append(@""" title=""");
			sb.Append(Resources.Messages.SortByUser);
			sb.Append(@""">");
			sb.Append(Resources.Messages.User);
			sb.Append((reverse && sortBy.Equals("user") ? " &uarr;" : ""));
			sb.Append((!reverse && sortBy.Equals("user") ? " &darr;" : ""));
			sb.Append("</a></b></p></td>");

			if(Request["Cat"] == null) { // Categories, if needed
				sb.Append("<td><p><b>");
				sb.Append(Resources.Messages.Categories);
				sb.Append("</b></p></td>");
			}
			sb.Append("</tr>");

			foreach(SortingGroup key in sortedPages.Keys) {
				List<ExtendedPageInfo> pageList = sortedPages[key];
				for(int i = 0; i < pageList.Count; i++) {
					string tmp = ((i + 1) % 2 != 0 ? "odd" : "even");

					if(i == 0) {
						// Add group header
						sb.Append("<tr>");
						if(sortBy == SortingMethod.Title) {
							sb.AppendFormat("<td colspan=\"{0}\" class=\"pagelistcelleven\"><b>{1}</b></td>",
								Request["Cat"] == null ? 5 : 4, key.Label);
						}
						else if(sortBy == SortingMethod.DateTime) {
							sb.AppendFormat("<td colspan=\"2\" class=\"pagelistcelleven\"></td><td colspan=\"{0}\" class=\"pagelistcelleven\"><b>{1}</b></td>",
								Request["Cat"] == null ? 3 : 2, key.Label);
						}
						else if(sortBy == SortingMethod.User) {
							sb.AppendFormat("<td colspan=\"3\" class=\"pagelistcelleven\"></td><td colspan=\"{0}\" class=\"pagelistcelleven\"><b>{1}</b></td>",
								Request["Cat"] == null ? 2 : 1, key.Label);
						}
						sb.Append("</tr>");
					}

					sb.Append("<tr>");
					// Page Name
					sb.Append(@"<td class=""pagelistcell");
					sb.Append(tmp);
					sb.Append(@""">");
					if(pageList[i].PageInfo.Name.Equals(Settings.DefaultPage)) sb.Append("<b>");
					sb.Append(@"<a href=""");
					sb.Append(Tools.UrlEncode(pageList[i].PageInfo.Name));
					sb.Append(Settings.PageExtension);
					sb.Append(@""">");
					sb.Append(pageList[i].Title);
					sb.Append("</a>");
					if(pageList[i].PageInfo.Name.Equals(Settings.DefaultPage)) sb.Append("</b>");
					sb.Append("</td>");
					// Message Count
					sb.Append(@"<td class=""pagelistcell");
					sb.Append(tmp);
					sb.Append(@""" style=""text-align: right;"">");
					int msg = pageList[i].MessageCount;
					if(msg > 0) {
						sb.Append(@"<a href=""");
						sb.Append(Tools.UrlEncode(pageList[i].PageInfo.Name));
						sb.Append(Settings.PageExtension);
						sb.Append(@"?Discuss=1"" title=""");
						sb.Append(Resources.Messages.Discuss);
						sb.Append(@""">");
						sb.Append(msg.ToString());
						sb.Append("</a>");
					}
					else sb.Append("&nbsp;");
					sb.Append("</td>");
					// Mod. Date/Time
					sb.Append(@"<td class=""pagelistcell");
					sb.Append(tmp);
					sb.Append(@"""><p>");
					string shift = "";
					if(Request.Cookies[Settings.CultureCookieName] != null) shift = Request.Cookies[Settings.CultureCookieName]["T"];
					sb.Append(Tools.AlignWithPreferences(pageList[i].DateTime, shift).ToString(Settings.DateTimeFormat));
					sb.Append("</p></td>");
					// Username
					sb.Append(@"<td class=""pagelistcell");
					sb.Append(tmp);
					sb.Append(@""">");
					sb.Append(Users.Instance.UserLink(pageList[i].User));
					sb.Append("</td>");
					// Cats
					if(Request["Cat"] == null) {
						CategoryInfo[] cats = Pages.Instance.GetCategoriesPerPage(pageList[i].PageInfo);
						sb.Append(@"<td class=""pagelistcell");
						sb.Append(tmp);
						sb.Append(@"""><small>");
						if(cats.Length == 0) {
							sb.Append(@"<a href=""AllPages.aspx?Cat=-"">");
							sb.Append(Resources.Messages.NC);
							sb.Append("</a>");
						}
						else {
							for(int k = 0; k < cats.Length; k++) {
								sb.Append(@"<a href=""AllPages.aspx?Cat=");
								sb.Append(Tools.UrlEncode(cats[k].Name));
								sb.Append(@""">");
								sb.Append(cats[k].Name);
								sb.Append("</a>");
								if(k != cats.Length - 1) sb.Append(", ");
							}
						}
						sb.Append("</small></td>");
					}
					sb.Append("</tr>");
				}
			}
			sb.Append("</table>");
			sb.Append("</div>");

			lblPageList.Text = sb.ToString();
        }

		public void PrintTree() {
			if(Request["View"] == null) return;
			else if(!Request["View"].ToLowerInvariant().Equals("tree")) return;

			StringBuilder sb = new StringBuilder();

			sb.Append(@"<div id=""TreeDiv"" ");
			sb.Append((Request["View"] != null && Request["View"].ToLowerInvariant().Equals("tree") ? "" : @"style=""display: none;"""));
			sb.Append(">");
			sb.Append(@"<a href=""AllPages.aspx"">");
			sb.Append(Resources.Messages.ViewList);
			sb.Append("</a><br /><br />");
			sb.Append(@"<p id=""PageTreeP"">");
			Pages pages = Pages.Instance;
			List<PageInfo> written = new List<PageInfo>();
			for(int i = 0; i < pages.AllPages.Count; i++) {
				written.Add(pages.AllPages[i]);
				PrintBlock(pages.AllPages[i], 0, written, sb);
			}
			sb.Append("</p></div>");

			lblTree.Text = sb.ToString();
		}

		private void PrintBlock(PageInfo info, int level, List<PageInfo> written, StringBuilder sb) {
			string space = "";
			for(int i = 0; i < level; i++)
				space += LevelSpace;

			PageContent content = Content.GetPageContent(info, true), tmp;
			Content.GetFormattedPageContent(info, true);

			WriteRow(content, space, sb);
			for(int i = 0; i < content.LinkedPages.Length; i++) {
				if(!written.Contains(content.LinkedPages[i])) {
					written.Add(content.LinkedPages[i]);
					PrintBlock(content.LinkedPages[i], level + 1, written, sb);
				}
				else {
					tmp = Content.GetPageContent(content.LinkedPages[i], true);
					WriteRow(tmp, space + LevelSpace, sb);
				}
			}
		}

		private string LevelSpace {
			get { return "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; }
		}

		private void WriteRow(PageContent content, string space, StringBuilder sb) {
			sb.Append(space);
			sb.Append(@"<a href=""");
			sb.Append(Tools.UrlEncode(content.PageInfo.Name));
			sb.Append(Settings.PageExtension);
			sb.Append(@""">");
			sb.Append((content.PageInfo.Name.Equals(Settings.DefaultPage) ? "<b>" : ""));
			sb.Append(content.Title);
			sb.Append((content.PageInfo.Name.Equals(Settings.DefaultPage) ? "</b>" : ""));
			sb.Append("</a><br />");
		}

	}

	public class PageComparer : IComparer<ExtendedPageInfo> {

		private string compare = "title";
		private bool reverse = false;

		public PageComparer(string compare, bool reverse) {
			this.compare = compare;
			this.reverse = reverse;
		}

		public int Compare(ExtendedPageInfo x, ExtendedPageInfo y) {
			if(reverse) {
				ExtendedPageInfo tmp = y;
				y = x;
				x = tmp;
			}
			switch(compare) {
				case "title":
					return string.Compare(x.Title, y.Title, false, CultureInfo.CurrentCulture);
				case "date":
					return x.DateTime.CompareTo(y.DateTime);
				case "user":
					return string.Compare(x.User, y.User, false, CultureInfo.CurrentCulture);
				default:
					throw new NotSupportedException("Invalid compare pattern " + compare);
			}
		}

	}

}
